require "Common/define"

--弹幕控制页面
UIBulletChat = {}
HelperFunc.SetUIEnv(UIBulletChat)
local this = UIBulletChat
this.poolNode = nil
this.hasInit = nil 
this.idle_bullet = {}
this.work_bullet = {}
this.queue_bullet = {}
this.bullet_chat_type = 1
this.work_bullet_y_list = {}

function UIBulletChat.Init( _type)
    this.bullet_chat_type = _type  or 1
    local name, package_name = getUIName(PanelNames.UIBulletChat);
    panelMgr:ShowUI(name, package_name, this.OnCreate, Config.useLocalUI);
end

--定义控件
function UIBulletChat.OnCreate(obj)
    if not this.hasInit then
        this.hasInit = true 
        this.gameObject = obj;
        this.poolNode = obj:GetChild("pool")
        this.poolNode.visible = false
 
        this.idle_bullet = {}
        this.position_controller = obj:GetController("position")
        this.position_controller:SetSelectedIndex(this.bullet_chat_type or 1) 
        this.dialog = obj:GetChild("dialog")
        this.dialog.text = ""
        this.dialog.promptText = getLanguage("BulletChat_InputHint")
        this.btn_bullet_chat = obj:GetChild("btnBulletChat")
        this.bullet_chat = obj:GetChild("bulletChat")
        this.bullet_chat_area_width = this.bullet_chat.width
        -- this.bullet_chat_area_height = this.bullet_chat.height
 
        if this.bullet_send_cd_time == nil then
            this.bullet_send_cd_time = dataTable.getDataTableByStringId("t_global",296,"f_int_value") or 10
        end 
        this.last_bullet_send_time = -1

        if this.bullet_play_cd_time == nil then
            this.bullet_play_cd_time = dataTable.getDataTableByStringId("t_global",291,"f_int_value") or 500
            this.bullet_play_cd_time = this.bullet_play_cd_time/1000
        end 
        this.last_bullet_play_time = -1

        if this.move_max_speed == nil then
            this.move_max_speed = dataTable.getDataTableByStringId("t_global",289,"f_int_value") or 30
        end
        if this.move_min_speed == nil then
            this.move_min_speed = dataTable.getDataTableByStringId("t_global",288,"f_int_value") or 10
        end

        if this.bullet_pipe_data == nil then
            this.bullet_pipe_data = {}
            local bullet_pipe_tbl = dataTable.getDataTableByStringId("t_global",290,"f_string_value")
            for _, v in pairs(bullet_pipe_tbl) do
                table.insert(this.bullet_pipe_data, v[2])
            end
            this.bullet_pipe_data_count = #this.bullet_pipe_data
        end

        if this.bullet_pipe_random_min == nil then
            this.bullet_pipe_random_min = dataTable.getDataTableByStringId("t_global",297,"f_int_value") or -50
        end
        if this.bullet_pipe_random_max == nil then
            this.bullet_pipe_random_max = dataTable.getDataTableByStringId("t_global",298,"f_int_value") or 50
        end

		
        this.update_deta_time = 0.033
        if this.updateTimer == nil then
            this.updateTimer = Timer.New(this.onFrameRender, this.update_deta_time, -1, false)
        else
            this.updateTimer:Reset(this.onFrameRender, this.update_deta_time, -1, false)
        end  
        this.updateTimer:Start()
        this.addEvent() 
        -- if this.bullet_chat_type == 1 then
        --     chatHandler.ReqGetLevitateCommentInfo( logicMgr.StoryMgr.cur_story_id )  
        -- else
            -- if BattlePlaybackManager.FightId then
            --     chatHandler.ReqGetLevitateCommentInfo( BattlePlaybackManager.FightId)   
            -- end
        -- end
        -- this.Test()
        if this.bullet_chat_type == 0 then
            this.BattleBulletData()
        end
    end 
end

function UIBulletChat.onFrameRender()
    if this.work_bullet ~= nil and next(this.work_bullet) ~= nil then
        for k, v in pairs(this.work_bullet) do
            local new_x = v.obj.x - this.update_deta_time * v.move_speed
            v.obj.x = new_x
            if new_x < -800 then
                this.RemoveBulletChat(v.obj)
                this.work_bullet_y_list[v.y] = nil
                table.remove(this.work_bullet, k) 
            end
        end
    end

    this.PopNewMessage()
end

function UIBulletChat.PopNewMessage() 
    if this.queue_bullet and #this.queue_bullet > 0 then 
        local cur_time = UnityEngine.Time.realtimeSinceStartup 
        local dis_time = cur_time - this.last_bullet_play_time
        if this.bullet_play_cd_time and dis_time > this.bullet_play_cd_time then
            local y = this.GetBulletYPos() --this.bullet_pipe_data[math.random(1, #this.bullet_pipe_data)]  
            if y ~= -1 then
                this.last_bullet_play_time = cur_time
                local index = #this.queue_bullet
                local content = this.queue_bullet[index]
                table.remove(this.queue_bullet, index)
                this.sendOneBullet(this.bullet_chat_area_width + 10, y, math.random(this.move_min_speed, this.move_max_speed), content);
            end
        end
    end
end

function UIBulletChat.GetBulletYPos() 
    for i=1, this.bullet_pipe_data_count, 1 do
        if this.work_bullet_y_list[ this.bullet_pipe_data[i] ] ~= true then
            this.work_bullet_y_list[ this.bullet_pipe_data[i] ] = true
            return this.bullet_pipe_data[i]
        end
    end
    return -1
end

function UIBulletChat.GetCanBlockBulletYPos()
    local index = math.random(this.bullet_pipe_data_count);
    return this.bullet_pipe_data[index];
end


function UIBulletChat.addEvent() 
    this.dialog.onFocusIn:Add(this.OnFocusInInput)
    this.dialog.onFocusOut:Add(this.OnFocusOutInput)
    this.dialog.onChanged:Add(this.OnInputChange)
    this.btn_bullet_chat.onClick:Add( this.onSendInputBulletChat)  
end

function UIBulletChat.removeEvent() 
    if this.dialog then
        this.dialog.onFocusIn:Remove(this.OnFocusInInput)
        this.dialog.onFocusOut:Remove(this.OnFocusOutInput)
        this.dialog.onChanged:Remove(this.OnInputChange)
    end
    if this.btn_bullet_chat then
        this.btn_bullet_chat.onClick:Clear()
    end
end

-- 输入框输入变化 
function UIBulletChat.OnInputChange() 
    local content = this.dialog.text  
    content = string.gsub(content,"\r", "")
    content = string.gsub(content,"\n", "") 
    if this.limit_send_content_count == nil then
        this.limit_send_content_count = dataTable.getDataTableByStringId("t_global",287,"f_int_value") or 30
    end  
    content = string.limitstr(content, this.limit_send_content_count)
    this.dialog.text = content 
end

-- 输入框聚集回调
function UIBulletChat.OnFocusInInput() 
    if this.bullet_chat_type == 1 then
        chatHandler.PauseAutoPlay()
    else
        chatHandler.PauseBattlePlay()
    end
end

-- 输入框聚集回调
function UIBulletChat.OnFocusOutInput()
    if this.bullet_chat_type == 0 then 
        chatHandler.StartBattlePlay()
    end

    if this.dialog then
        local content = this.dialog.text
        content = string.gsub(content,"\r", "")
        content = string.gsub(content,"\n", "")
        if content ~= "" then   
            this.SendInputBulletChat()   
        end
    end 
end

function UIBulletChat.onSendInputBulletChat()   
    if not this.input_foucus then
        this.SendInputBulletChat()  
    end
end

function UIBulletChat.SendInputBulletChat()  
    if this.last_send_time then
        if UnityEngineTime.realtimeSinceStartup - this.last_send_time < 1 then
            return
        end
    end
    this.last_send_time = UnityEngineTime.realtimeSinceStartup
    local content = this.dialog.text
    content = string.gsub(content,"\r", "")
    content = string.gsub(content,"\n", "")
    if content == "" then
        UISysTips.AddMsg(getLanguage("Sys_MsgInputEmpty"))
        return
    end
    local cur_time = UnityEngine.Time.realtimeSinceStartup
    if this.last_bullet_send_time ~= nil and this.last_bullet_send_time ~= -1 then 
        local dis_time = cur_time - this.last_bullet_send_time 
        if dis_time <= this.bullet_send_cd_time then
            UISysTips.AddMsg( getLanguage("BulletChat_Msg_CD") )
            return
        end

    end
      
    if this.limit_send_content_count == nil then
        this.limit_send_content_count = dataTable.getDataTableByStringId("t_global",287,"f_int_value") or 30
    end
    if this.black_word_replace_str == nil then
        this.black_word_replace_str = dataTable.getDataTableByStringId("t_global",280,"f_string_value") or "*"
    end
    content = string.limitstr(content, this.limit_send_content_count);
    local source_content = content
    --blockword
    content = BlockWordFilter(content, this.black_word_replace_str)
    --local blockword = dataTable.getDataTable("t_blockword")
    --for k, v in pairs(blockword) do
    --    content = string.gsub(content, v.f_Value, this.black_word_replace_str)
    --end
    if source_content ~= content then
        UISysTips.AddMsg(getLanguage("Achieve_HeroComment_Msg_BlockWord"))
        this.dialog.text = content
        return
    end

    this.last_bullet_send_time = cur_time 
    if this.bullet_chat_type == 1 then
        chatHandler.ReqLevitateComment( logicMgr.StoryMgr.cur_chapter_id, logicMgr.StoryMgr.cur_story_id, content )
        local key = logicMgr.HeroManager.GetRoleId()..logicMgr.StoryMgr.cur_story_id
        local history_tbl = nil 
        local history_str = Util.GetPlayerPrefs( key )  
        if history_str and history_str ~= "" and history_str ~= "null" then
            history_tbl = decodeJsonStrToTabel(history_str)
        end
        if history_tbl == nil then history_tbl = {} end
        if type(history_tbl) ~= "table" then  history_tbl = {} end 
        table.insert(history_tbl, content)
        if #history_tbl > 20 then
            table.remove(history_tbl, 1)
        end
        Util.SetPlayerPrefs(key, getJsonStr(history_tbl))
        
    else
        local key = BattlePlaybackManager.FightId
        if key then
            key = logicMgr.HeroManager.GetRoleId()..key
            local history_tbl = nil 
            local history_str = Util.GetPlayerPrefs( key ) 
            if history_str and history_str ~= "" and history_str ~= "null" then
                history_tbl = decodeJsonStrToTabel(history_str)
            end
            if history_tbl == nil then history_tbl = {} end
            table.insert(history_tbl, content)
            if #history_tbl > 20 then
                table.remove(history_tbl, 1)
            end
            Util.SetPlayerPrefs(key, getJsonStr(history_tbl))
        end
        this.dialog.text = ""
    end 

    
    -- local y = this.bullet_pipe_data[math.random(1, #this.bullet_pipe_data)] --+ math.random(this.bullet_pipe_random_min, this.bullet_pipe_random_max)
    local y = this.GetBulletYPos() 
    if y ~= -1 then
        this.sendOneBullet(this.bullet_chat_area_width + 10, y, math.random(this.move_min_speed, this.move_max_speed), content);
    else
        table.insert(this.queue_bullet, content) 
    end
end

function UIBulletChat.StopTimer()
    if this.updateTimer ~= nil then
        this.updateTimer:Stop()
        this.updateTimer = nil
    end
end

function UIBulletChat.OnDestroy()
    this.hasInit=false
    this.StopTimer()
    this.removeEvent()
     
    this.poolNode = nil
    this.gameObject = nil 
    this.position_controller = nil
    this.dialog = nil
    this.btn_bullet_chat = nil
    this.bullet_chat = nil
 
    this.limit_send_content_count = nil 
    this.black_word_replace_str = nil
  
    this.bullet_send_cd_time = nil 
    this.last_bullet_send_time = nil
    this.bullet_play_cd_time = nil
    this.last_bullet_play_time = nil
    this.move_max_speed = nil 
    this.move_min_speed = nil  

    this.bullet_pipe_random_min = nil 
    this.bullet_pipe_random_max = nil 
    for _, v in pairs(this.work_bullet) do
        v.obj = nil
    end
    this.work_bullet = {}
    this.queue_bullet = {}

    for _, v in pairs(this.idle_bullet) do
        v = nil
    end
    this.idle_bullet = {}

    this.local_bullet_play_cd_time = nil
    this.bullet_pipe_data = nil
    this.bullet_pipe_data_count = nil
	this.work_bullet_y_list = {}
end

function  UIBulletChat.GetTextMesh()
    local item = nil 

    if next(this.idle_bullet) == nil then 
        item = newGComponent("BulletChatText", "UIBulletChat") 
        if item then
            item.gameObjectName = "BulletChatText"
        end

    else
        item = this.idle_bullet[1]
        table.remove(this.idle_bullet, 1)
    end
    if this.bullet_chat_type == 2 then
        item:GetController("position").selectedIndex = 1;
    else
        item:GetController("position").selectedIndex = 0;
    end
    this.bullet_chat:AddChild(item)
    return item
end
  
 
function UIBulletChat.RemoveBulletChat(item)
    this.poolNode:AddChild(item)
    table.insert(this.idle_bullet, item)
end

-- 发送弹幕请求返回
function UIBulletChat.ResLevitateComment()  
    if this.dialog then
        this.dialog.text = ""
    end
end

-- 本地剧情弹幕
function UIBulletChat.LocalStoryBullet()
    local flag = false 
    if this.bullet_play_cd_time == nil then
        this.bullet_play_cd_time = dataTable.getDataTableByStringId("t_global",291,"f_int_value") or 500
        this.bullet_play_cd_time = this.bullet_play_cd_time/1000
    end 

    if this.last_bullet_play_time then
        if UnityEngine.Time.realtimeSinceStartup - this.last_bullet_play_time < this.bullet_play_cd_time then
            flag = true
        end
    end
    local story_chat_id = logicMgr.StoryMgr.cur_story_id
    if story_chat_id then
        local cur_story_data = G.dataTable["t_story"][tostring(story_chat_id)] 
        if cur_story_data and cur_story_data["f_PresetBullet"] then --f_PresetBullet
            local preset_bullet = cur_story_data["f_PresetBullet"] 
            if preset_bullet and type(preset_bullet) ~= "string" then
                for _, v in pairs(preset_bullet) do
                    if flag then
                        table.insert(this.queue_bullet, v)
                    else
                        this.GenNewBullet(v)
                        flag = true
                    end
                end
            end
        end
            
        -- local key = logicMgr.HeroManager.GetRoleId()..story_chat_id
        -- local history_str = Util.GetPlayerPrefs(key)
        -- if history_str and history_str ~= "" and history_str ~= "null" then 
        --     local history_tbl = decodeJsonStrToTabel(history_str) 
        --     if history_tbl ~= nil and type(history_tbl) =="table" then
        --         for _, v in pairs(history_tbl) do
        --             if v and type(v) == "string" and  v ~= "" then
        --                 if flag then
        --                     table.insert(this.queue_bullet, v)
        --                 else
        --                     this.GenNewBullet(v)
        --                     flag = true
        --                 end
        --             end
        --         end
        --     end
        -- end 
    end
end

-- 拉取弹幕返回
function UIBulletChat.PlayNetStoryComment( data,notStory)
    if logicMgr.FuncOpenManager.isOpen(Config.FuncOpenType.BulletChat) ~= true then
        return
    end
    local flag = false
    if this.bullet_play_cd_time == nil then
        this.bullet_play_cd_time = dataTable.getDataTableByStringId("t_global",291,"f_int_value") or 500
        this.bullet_play_cd_time = this.bullet_play_cd_time/1000
    end 

    if this.last_bullet_play_time then
        if UnityEngine.Time.realtimeSinceStartup - this.last_bullet_play_time < this.bullet_play_cd_time then
            flag = true
        end
    end 
    local all_bullet_data = {}
    if data then 
        for _, v in pairs(data) do 
            if v and type(v) == "string" and  v ~= "" then
                if flag then
                    table.insert(this.queue_bullet, v)
                else
                    this.GenNewBullet(v)
                    flag = true
                end  
                all_bullet_data[v] = true
            end
        end
    end
    if (not notStory)then
        local story_chat_id = logicMgr.StoryMgr.cur_story_id
        if story_chat_id then
            local key = logicMgr.HeroManager.GetRoleId()..story_chat_id
            local history_str = Util.GetPlayerPrefs(key)
            if history_str and history_str ~= "" and history_str ~= "null" then
                local history_tbl = decodeJsonStrToTabel(history_str)
                if history_tbl ~= nil and type(history_tbl) =="table" then
                    for _, v in pairs(history_tbl) do
                        if v and type(v) == "string" and  v ~= "" then
                            if not all_bullet_data[v] then
                                if flag then
                                    table.insert(this.queue_bullet, v)
                                else
                                    this.GenNewBullet(v)
                                    flag = true
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end

  
-- 拉取弹幕返回
function UIBulletChat.ResGetLevitateCommentInfo( msg )
    if logicMgr.FuncOpenManager.isOpen(Config.FuncOpenType.BulletChat) ~= true then
        return
    end
    local flag = false
    if this.bullet_play_cd_time == nil then
        this.bullet_play_cd_time = dataTable.getDataTableByStringId("t_global",291,"f_int_value") or 500
        this.bullet_play_cd_time = this.bullet_play_cd_time/1000
    end 

    if this.last_bullet_play_time then
        if UnityEngine.Time.realtimeSinceStartup - this.last_bullet_play_time < this.bullet_play_cd_time then
            flag = true
        end
    end
    -- local story_chat_id = logicMgr.StoryMgr.cur_story_id
    -- if story_chat_id then
    --     local cur_story_data = G.dataTable["t_story"][tostring(story_chat_id)] 
    --     if cur_story_data and cur_story_data["f_PresetBullet"] then --f_PresetBullet
    --         local preset_bullet = cur_story_data["f_PresetBullet"] 
    --         if preset_bullet and type(preset_bullet) ~= "string" then
    --             for _, v in pairs(preset_bullet) do
    --                 if flag then
    --                     table.insert(this.queue_bullet, v)
    --                 else
    --                     this.GenNewBullet(v)
    --                     flag = true
    --                 end
    --             end
    --         end
    --     end
            
    --     local history_str = Util.GetPlayerPrefs(story_chat_id) 
    --     if history_str and history_str ~= "" and history_str ~= "null" then 
    --         local history_tbl = decodeJsonStrToTabel(history_str) 
    --         if history_tbl ~= nil and type(history_tbl) =="table" then
    --             for _, v in pairs(history_tbl) do
    --                 if v and type(v) == "string" and  v ~= "" then
    --                     if flag then
    --                         table.insert(this.queue_bullet, v)
    --                     else
    --                         this.GenNewBullet(v)
    --                         flag = true
    --                     end
    --                 end
    --             end
    --         end
    --     end 
    -- end
  
    if msg.comments and msg.comments.Comment then 
        for _, v in pairs(msg.comments.Comment) do 
            if flag then
                table.insert(this.queue_bullet, v)
            else
                this.GenNewBullet(v)
                flag = true
            end 
        end
    end  
end

--- 发送一条弹幕,不被遮挡
function UIBulletChat.GenNewBullet( content )
    local y = this.GetBulletYPos() 
    if y ~= -1 then
        this.last_bullet_play_time = UnityEngine.Time.realtimeSinceStartup
        this.sendOneBullet(this.bullet_chat_area_width + 1, y, math.random(this.move_min_speed, this.move_max_speed), content);
    else
        table.insert(this.queue_bullet, content)
    end
end

--- 发送一条弹幕,可被遮挡
function UIBulletChat.GenNewCanBlockBullet(content)
    local y = this.GetCanBlockBulletYPos()
    this.last_bullet_play_time = UnityEngine.Time.realtimeSinceStartup
    this.sendOneBullet(this.bullet_chat_area_width + 1, y, math.random(this.move_min_speed, this.move_max_speed), content);
end

---立即滚动一条弹幕
function UIBulletChat.sendOneBullet(x,y,speed,content)
    local msg_obj = this.GetTextMesh()
    msg_obj.x = x
    msg_obj.y = y
    local text_content = msg_obj:GetChild("text")
    text_content.text = content
    local item = {}
    item.obj = msg_obj
    item.y = y
    item.move_speed = speed
    table.insert(this.work_bullet, item)
end

--- 战斗弹幕
function UIBulletChat.BattleBulletData()
    local presetbullet_tbl = dataTable.getDataTable("t_presetbullet") 
    local flag = false
    local key = BattlePlaybackManager.FightId
    if key then
        key = logicMgr.HeroManager.GetRoleId()..key
        local history_str = Util.GetPlayerPrefs(key) 
        if history_str and history_str ~= "" and history_str ~= "null" then 
            local history_tbl = decodeJsonStrToTabel(history_str) 
            if history_tbl ~= nil then
                for _, v in pairs(history_tbl) do
                    if flag then
                        table.insert(this.queue_bullet, v)
                    else
                        this.GenNewBullet(v)
                        flag = true
                    end
                end
            end
        end
    end

    for _, v in pairs(presetbullet_tbl) do
        if v and v.f_PresetBullet and v.f_PresetBullet ~= "" then
            if flag then
                table.insert(this.queue_bullet, v.f_PresetBullet)
            else
                this.GenNewBullet(v.f_PresetBullet)
                flag = true
            end
        end
    end
end

-- 测试样例
function UIBulletChat.Test()
    local msg = {}
    msg.errorCode = 0
    msg.comments = {}
    msg.comments.Comment ={}
    table.insert(msg.comments.Comment, "0000000000000")
    table.insert(msg.comments.Comment, "11111111111111")
    table.insert(msg.comments.Comment, "3333333333333")
    table.insert(msg.comments.Comment, "4444444444444")
    table.insert(msg.comments.Comment, "5555555555555")
    table.insert(msg.comments.Comment, "666666666666666")
    this.ResGetLevitateCommentInfo( msg ) 
end

return UIBulletChat